﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.DataAccess.SqlServer.Model;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.DataAccess.Implementaciones.SQL
{
    /// <summary>
    /// Clase de las operaciones de Acceso a Datos para el módulo de Carga de Archivos.
    /// </summary>
    public class CargasArchivosDao : ICargasArchivosDao
    {
        /// <summary>
        /// Obtiene los archivos Autorizados para realizar una recarga
        /// </summary>
        /// <param name="idUsuario">id del usuario al cual autorizaron la recarga</param>
        public IList<ListaInfo> GetArchivosAutorizados(int idUsuario)
        {
            List<ListaInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var idsArchivos = (from bitacora in context.MIAP_BITACORA_GENERAL
                                   join miapSolicitud in context.MIAP_SOLICITUD on bitacora.ID_BITACORA_GENERAL equals miapSolicitud.ID_BITACORA_GENERAL
                                   join miapBitacoraArchivo in context.MIAP_BITACORA_ARCHIVO on bitacora.ID_BITACORA_GENERAL equals miapBitacoraArchivo.ID_BITACORA_GENERAL
                                   join miapCargaArchivo in context.MIAP_CARGA_ARCHIVO on miapBitacoraArchivo.ID_ARCHIVO equals miapCargaArchivo.ID_ARCHIVO

                                   where
                                       bitacora.ID_TIPO_PROCESO == (int)TipoProceso.RespuestaSolicitud
                                       && miapSolicitud.ID_ESTATUS_SOLICITUD == (int)EstatusSolicitud.Autorizada
                                       && miapSolicitud.ID_SOLICITANTE == idUsuario && miapCargaArchivo.VERSION == miapBitacoraArchivo.VERSION
                                   select new ListaInfo
                                   {
                                       IdArchivo = miapCargaArchivo.ID_ARCHIVO,
                                       NombreArchivo = miapCargaArchivo.MIAP_ARCHIVO.NOMBRE,
                                       Version = miapCargaArchivo.VERSION ?? string.Empty,
                                       Año = miapCargaArchivo.AÑO,
                                       Mes = miapCargaArchivo.MES,
                                       FechaProceso = miapCargaArchivo.FECHA_MODIFICACION
                                   });
                result = idsArchivos.ToList();
            }
            return result;
        }

        /// <summary>
        /// Obtiene la informacion de carga de un archivo
        /// </summary>
        /// <param name="idArchivo">Id del archivo a revisar</param>
        /// <param name="version">si es un archivo versionable indica la version del archivo</param>
        /// <returns></returns>
        public List<CargaArchivoInfo> GetInformacionArchivoCarga(int idArchivo, string version)
        {
            List<CargaArchivoInfo> result;
            using (var context = new MIAPDBEntities())
            {
                var query = from carga in context.MIAP_CARGA_ARCHIVO
                            where carga.ID_ARCHIVO == idArchivo
                            && (string.IsNullOrEmpty(version) || carga.VERSION == version)
                            select new CargaArchivoInfo
                                {
                                    IdCargaArchivo = carga.ID_CARGA_ARCHIVO,
                                    IdArchivo = carga.ID_ARCHIVO,
                                    NombreArchivo = carga.MIAP_ARCHIVO.NOMBRE,
                                    NombreProyecto = carga.MIAP_ARCHIVO.MIAP_PROYECTO.NOMBRE,
                                    Mes = carga.MES,
                                    Año = carga.AÑO,
                                    Version = carga.VERSION,
                                    IdProyecto = carga.MIAP_ARCHIVO.ID_PROYECTO,
                                    FechaProceso = carga.FECHA_MODIFICACION
                                };
                result = query.ToList();
            }
            return result;
        }

        /// <summary>
        /// Registra una nueva carga de archivo en el sistema
        /// </summary>
        /// <param name="archivo">informacion del archivo que registraremos la carga</param>
        /// <param name="user">usuario que esta realizando la carga</param>
        public int CargaArchivo(CargaArchivoInfo archivo, UsuarioInfo user)
        {
            int idBitGral;
            using (var context = new MIAPDBEntities())
            {
                var bitGeneral = new MIAP_BITACORA_GENERAL
                    {
                        AÑO = archivo.Año.Value,
                        MES = archivo.Mes.Value,
                        USUARIO_CREACION = user.AliasUsuario,
                        USUARIO_ACTUALIZACION = user.AliasUsuario,
                        FECHA_ACTUALIZACION = DateTime.Now,
                        FECHA_CREACION = DateTime.Now,
                        ID_TIPO_PROCESO = (int)TipoProceso.Carga,
                        ID_USUARIO = user.IdUsuario,
                        ID_ESTATUS_PROCESO = (int)EstatusProceso.Inicio
                    };
                context.MIAP_BITACORA_GENERAL.Add(bitGeneral);

                var bitArchivo = new MIAP_BITACORA_ARCHIVO
                    {
                        ID_BITACORA_GENERAL = bitGeneral.ID_BITACORA_GENERAL,
                        ID_ARCHIVO = archivo.IdArchivo.Value,
                        NOMBRE_ARCHIVO = archivo.NombreArchivoSubir,
                        VERSION = archivo.Version,
                        USUARIO_CREACION = user.AliasUsuario,
                        USUARIO_ACTUALIZACION = user.AliasUsuario,
                        FECHA_ACTUALIZACION = DateTime.Now,
                        FECHA_CREACION = DateTime.Now,
                    };

                context.MIAP_BITACORA_ARCHIVO.Add(bitArchivo);

                var cargaArchivo = new MIAP_CARGA_ARCHIVO
                    {
                        ID_ARCHIVO = archivo.IdArchivo.Value,
                        AÑO = archivo.Año.Value,
                        MES = archivo.Mes.Value,
                        USUARIO_CREACION = user.AliasUsuario,
                        FECHA_CREACION = DateTime.Now,
                        FECHA_MODIFICACION = DateTime.Now,
                        USUARIO_MODIFICACION = user.AliasUsuario,
                        VERSION = archivo.Version,
                        VERSION_VALIDA = false,
                    };

                context.MIAP_CARGA_ARCHIVO.Add(cargaArchivo);

                var bitGralCarga = new MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                    {
                        ID_BITACORA_GENERAL = bitGeneral.ID_BITACORA_GENERAL,
                        ID_CARGA_ARCHIVO = cargaArchivo.ID_CARGA_ARCHIVO,
                        USUARIO_CREACION = user.AliasUsuario,
                        USUARIO_ACTUALIZACION = user.AliasUsuario,
                        FECHA_ACTUALIZACION = DateTime.Now,
                        FECHA_CREACION = DateTime.Now,
                    };

                context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO.Add(bitGralCarga);

                context.SaveChanges();
                idBitGral = bitGeneral.ID_BITACORA_GENERAL;
            }
            return idBitGral;
        }

        /// <summary>
        /// Registra una re-Carga de archivo en el sistema
        /// </summary>
        /// <param name="archivo">informacion del archivo que registraremos la carga</param>
        /// <param name="user">usuario que esta realizando la carga</param>
        public int RecargaArchivo(CargaArchivoInfo archivo, UsuarioInfo user)
        {
            int idBitGral;
            using (var context = new MIAPDBEntities())
            {
                var bitGeneral = new MIAP_BITACORA_GENERAL
                {
                    AÑO = archivo.Año.Value,
                    MES = archivo.Mes.Value,
                    USUARIO_CREACION = user.AliasUsuario,
                    USUARIO_ACTUALIZACION = user.AliasUsuario,
                    FECHA_ACTUALIZACION = DateTime.Now,
                    FECHA_CREACION = DateTime.Now,
                    ID_TIPO_PROCESO = (int)TipoProceso.Recarga,
                    ID_USUARIO = user.IdUsuario,
                    ID_ESTATUS_PROCESO = (int)EstatusProceso.Inicio
                };

                context.MIAP_BITACORA_GENERAL.Add(bitGeneral);

                var bitArchivo = new MIAP_BITACORA_ARCHIVO
                {
                    ID_BITACORA_GENERAL = bitGeneral.ID_BITACORA_GENERAL,
                    ID_ARCHIVO = archivo.IdArchivo.Value,
                    NOMBRE_ARCHIVO = archivo.NombreArchivoSubir,
                    VERSION = archivo.Version,
                    USUARIO_CREACION = user.AliasUsuario,
                    USUARIO_ACTUALIZACION = user.AliasUsuario,
                    FECHA_ACTUALIZACION = DateTime.Now,
                    FECHA_CREACION = DateTime.Now,
                };

                context.MIAP_BITACORA_ARCHIVO.Add(bitArchivo);

                var cargaArchivo = (from carga in context.MIAP_CARGA_ARCHIVO
                                    where carga.ID_CARGA_ARCHIVO == archivo.IdCargaArchivo
                                    select carga).Single();
                cargaArchivo.FECHA_MODIFICACION = DateTime.Now;
                cargaArchivo.USUARIO_MODIFICACION = user.AliasUsuario;

                var bitGralCarga = new MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                {
                    ID_BITACORA_GENERAL = bitGeneral.ID_BITACORA_GENERAL,
                    ID_CARGA_ARCHIVO = cargaArchivo.ID_CARGA_ARCHIVO,
                    USUARIO_CREACION = user.AliasUsuario,
                    USUARIO_ACTUALIZACION = user.AliasUsuario,
                    FECHA_ACTUALIZACION = DateTime.Now,
                    FECHA_CREACION = DateTime.Now,
                };

                context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO.Add(bitGralCarga);
                // Actualizamos la solicitud del archivo a recargada.
                var solicitud = (from bitGral in context.MIAP_BITACORA_GENERAL
                                 join miapBitacoraArchivo in context.MIAP_BITACORA_ARCHIVO on
                                     bitGral.ID_BITACORA_GENERAL equals miapBitacoraArchivo.ID_BITACORA_GENERAL
                                 join miapSolicitud in context.MIAP_SOLICITUD on bitGral.ID_BITACORA_GENERAL equals
                                     miapSolicitud.ID_BITACORA_GENERAL
                                 where
                                     miapBitacoraArchivo.ID_ARCHIVO == archivo.IdArchivo &&
                                     miapBitacoraArchivo.VERSION == archivo.Version
                                     && bitGral.ID_TIPO_PROCESO == (int)TipoProceso.RespuestaSolicitud
                                     && miapSolicitud.ID_ESTATUS_SOLICITUD == (int)EstatusSolicitud.Autorizada
                                 select miapSolicitud).Single();

                solicitud.ID_ESTATUS_SOLICITUD = (int)EstatusSolicitud.Recargada;
                solicitud.ID_BITACORA_GENERAL = bitGeneral.ID_BITACORA_GENERAL;
                solicitud.FECHA_ACTUALIZACION = DateTime.Now;
                solicitud.USUARIO_ACTUALIZACION = user.AliasUsuario;

                context.SaveChanges();
                idBitGral = bitGeneral.ID_BITACORA_GENERAL;
            }
            return idBitGral;
        }

        /// <summary>
        /// si existio algun error detectado por nuestra aplicación en la ejecucion de proyectos o 
        /// carga de archivos este se marcará con estatus de error
        /// </summary>
        /// <param name="idBitGeneral">Id del registro que fue iniciado</param>
        /// <param name="usuario">usuario quien realiza el proceso</param>
        public void SetProcesoError(int idBitGeneral, string usuario)
        {
            using (var context = new MIAPDBEntities())
            {
                var bit =
                    (from bitacora in context.MIAP_BITACORA_GENERAL
                     where bitacora.ID_BITACORA_GENERAL == idBitGeneral
                     select bitacora).Single();
                bit.ID_ESTATUS_PROCESO = (int)EstatusProceso.Finalizado_Errores;
                bit.FECHA_ACTUALIZACION = DateTime.Now;
                bit.USUARIO_ACTUALIZACION = usuario;
                context.SaveChanges();
            }
        }
    }
}
